package com.abe.libquick.utils.quick;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Base64;
import android.widget.ImageView;

import com.abe.libcore.utils.context.ContextUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


@SuppressWarnings("deprecation")
public class BitmapUtil {

    private static BitmapUtil util;
    private static int zoomLevel = 0;

    public static BitmapUtil getInstance() {
        return util == null ? new BitmapUtil() : util;
    }

    public static BitmapUtil setZoomLevel(int level) {
        zoomLevel = level;
        return getInstance();
    }

    /*****************************************************************************************/

    /**
     * 释放ImageView持有资源
     */
    public static void releaseImageViewResource(ImageView imageView) {
        if (imageView == null)
            return;
        Drawable drawable = imageView.getDrawable();
        if (drawable != null && drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            releaseBitmapDrawable(bitmapDrawable);
        }
        Drawable backgroundDrawable = imageView.getBackground();
        if (backgroundDrawable != null
                && backgroundDrawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) backgroundDrawable;
            releaseBitmapDrawable(bitmapDrawable);
        }
    }

    public static void releaseBitmapDrawable(BitmapDrawable bitmapDrawable) {
        Bitmap bitmap = bitmapDrawable.getBitmap();
        releaseBitmap(bitmap);
    }

    public static void releaseBitmap(Bitmap bitmap) {
        if (bitmap != null && !bitmap.isRecycled()) {
            bitmap.recycle();
            System.out.println("recycle");
        }
    }

    /*****************************************************************************************/

    /**
     * 加载 drawable 获取资源图片
     * <p>
     * OOM_Image_Error
     */
    public static Drawable readDrawable(int resId) {
        InputStream is = ContextUtils.Companion.getContext().getResources()
                .openRawResource(resId);
        return readDrawable(is);
    }

    /**
     * InputStream转Drawable 获取资源图片
     */
    public static Drawable readDrawable(InputStream is) {
        return new BitmapDrawable(readLocalBitmap(is));
    }

    /**
     * InputStream转Bitmap
     */
    public static Bitmap readLocalBitmap(InputStream is) {
        Bitmap bitmap = null;
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(is, null, opts);
        opts.inSampleSize = computeSampleSize(opts, -1, zoomLevel * zoomLevel);
        opts.inPreferredConfig = Bitmap.Config.RGB_565;
        opts.inJustDecodeBounds = false;
        opts.inInputShareable = true;
        opts.inPurgeable = true;

        try {
            bitmap = BitmapFactory.decodeStream(is, null, opts);
        } catch (Exception e) {
            //** handle exception */
            e.printStackTrace();
        }
        return bitmap;
    }

    /**
     * 加载本地图片
     */
    public static Bitmap readLocalBitmap(String filePath) {
        Bitmap bitmap = null;
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, opts);
        opts.inSampleSize = computeSampleSize(opts, -1, zoomLevel * zoomLevel);
        opts.inPreferredConfig = Bitmap.Config.RGB_565;
        opts.inJustDecodeBounds = false;
        opts.inInputShareable = true;
        opts.inPurgeable = true;
        try {
            bitmap = BitmapFactory.decodeFile(filePath, opts);
        } catch (Exception e) {
            //** handle exception */
            e.printStackTrace();
        }
        return bitmap;
    }

    public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
        int initialSize = computeInitialSampleSize(options, minSideLength,
                maxNumOfPixels);
        int roundedSize;
        if (initialSize <= 8) {
            roundedSize = 1;
            while (roundedSize < initialSize) {
                roundedSize <<= 1;
            }
        } else {
            roundedSize = (initialSize + 7) / 8 * 8;
        }
        return roundedSize;
    }

    private static int computeInitialSampleSize(BitmapFactory.Options options,
                                                int minSideLength, int maxNumOfPixels) {
        double w = options.outWidth;
        double h = options.outHeight;
        int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
                .sqrt(w * h / maxNumOfPixels));
        int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
                Math.floor(w / minSideLength), Math.floor(h / minSideLength));
        if (upperBound < lowerBound) {
            // return the larger one when there is no overlapping zone.
            return lowerBound;
        }
        if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
            return 1;
        } else if (minSideLength == -1) {
            return lowerBound;
        } else {
            return upperBound;
        }
    }

    public static String bitmapToString(Bitmap bitmap) {
        try {
            return bitmap != null ? Base64.encodeToString(Bitmap2Bytes(bitmap),
                    Base64.DEFAULT) : "";
        } catch (Exception e) {
            return "";
        }
    }

    public static byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }

    public static Bitmap Bytes2Bitmap(byte[] b) {
        if (b.length != 0) {
            return BitmapFactory.decodeByteArray(b, 0, b.length);
        } else {
            return null;
        }
    }

    public static Bitmap stringToBitmap(String base64) {
        try {
            return Bytes2Bitmap(Base64.decode(base64, Base64.DEFAULT));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Bitmap getImageViewBitmap(ImageView imageView) {
        try {
            return ((BitmapDrawable) imageView.getDrawable()).getBitmap();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void saveBitmapToJPG(Bitmap bitmap, File photo) {
        try {
            Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(),
                    bitmap.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(newBitmap);
            canvas.drawColor(Color.WHITE);
            canvas.drawBitmap(bitmap, 0, 0, null);
            OutputStream stream = new FileOutputStream(photo);
            newBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
